<?php

// +----------------------------------------------------------------------
// | URL解析、路由和调度
// +----------------------------------------------------------------------
//支持的URL模式
define('URL_COMMON', 0);   //普通模式
define('URL_PATHINFO', 1);   //PATHINFO模式
define('URL_REWRITE', 2);   //REWRITE模式

class dispatcher {

	//URL映射到控制器
	static public function dispatch() {
		$urlMode = C('sys_url_mode');
		//入口文件
		if ($urlMode == URL_REWRITE) {
			$url = dirname(_PHP_FILE_);
			if ($url == '/' || $url == '\\')
				$url = '';
			define('PHP_FILE', $url);
		}else {
			define('PHP_FILE', _PHP_FILE_);
		}

		self::getPathInfo();
		$rule = $params = array();
		$regx = trim($_SERVER['PATH_INFO'], '/');
		$depr = C('sys_url_depr');

		//有phpinfo路径 或者 开启了子域名 则进行路由参数配置
		if ($regx || C('sys_domain')) {
			$params = explode($depr, $regx); //url参数
			$subDomain = '';
			if (C('sys_domain')) {
				C('sys_route', true); //开启子域名自动开启路由开关
				$subDomain = strtolower(substr($_SERVER['HTTP_HOST'], 0, strpos($_SERVER['HTTP_HOST'], '.')));
				define('SUB_DOMAIN', $subDomain);
				$rule = C('sys_domain_rules');
			} elseif (C('sys_route')) {
				$rule = C('sys_route_rules');
			}

			//处理路由规则
			if (empty($rule) || !self::routerCheck($rule, $params)) {
				//没有路由 按url默认规则分配参数
				$module_list = C('sys_module_list');
				$module_list[] = C('sys_default_module');
				if (isset($params[0]) && in_array($params[0], $module_list)) {
					$var[C('var_module')] = array_shift($params);
				} else {
					$var[C('var_module')] = C('sys_default_module');
				}
				if (isset($params[0]))
					$var[C('var_controller')] = array_shift($params);
				if (isset($params[0]))
					$var[C('var_action')] = array_shift($params);
				// 解析剩余的URL参数
				$res = preg_replace('@(\w+)\/([^,\/]+)@e', '$var[\'\\1\']="\\2";', implode('/', $params));
				$_GET = array_merge($var, $_GET);
			}
		}

		// 获取分组 模块和操作名称
		define('MODULE_NAME', self::getModule(C('var_module')));
		define('CONTROLLER_NAME', self::getController(C('var_controller')));
		define('ACTION_NAME', self::getAction(C('var_action')));

		// 当前页面地址
		define('_SELF_', $_SERVER['REQUEST_URI']);
		//path_info地址
		define('_INFO_', $_SERVER['PATH_INFO']);

		// 当前网站地址
		$site_url = C('sys_domain') ? get_url() : '';
		define('_APP_', $site_url . PHP_FILE);
		define('_URL_', _APP_);

		//模块、控制、方法的URL
		if($urlMode){
			define('_M_', ( $subDomain || MODULE_NAME == C('sys_default_module') ) ? _URL_ : _URL_ . '/' . MODULE_NAME);
			define('_C_', _M_ . $depr . CONTROLLER_NAME);
			define('_A_', _C_ . $depr . ACTION_NAME);
		}else{
			define('_M_', _URL_.'?m=' . MODULE_NAME);
			define('_C_', _M_ . '&c=' . CONTROLLER_NAME);
			define('_A_', _C_ . '&a=' . ACTION_NAME);
		}

		//保证$_REQUEST正常取值
		$_REQUEST = array_merge($_POST, $_GET);
	}

	//路由检测
	static public function routerCheck($routers, $params) {
		$params2 = $params;
		$router_name = defined('SUB_DOMAIN') ? SUB_DOMAIN : array_shift($params);

		// 简单路由定义：array('分组','模块','操作名','var1,var2'),
		if (isset($routers[$router_name]) && !empty($routers[$router_name])) {
			$rule = $routers[$router_name];
			$var[C('var_module')] = !empty($rule[0]) ? $rule[0] : array_shift($params);
			$var[C('var_controller')] = !empty($rule[1]) ? $rule[1] : array_shift($params);
			$var[C('var_action')] = !empty($rule[2]) ? $rule[2] : array_shift($params);

			// 处理路由规则的路由参数
			$vars = $rule[3];
			if ($vars) {
				$vars = explode(',', $vars);
				for ($i = 0; $i < count($vars); $i++) {
					$tmp = array_shift($params);
					if ($tmp !== null)
						$var[$vars[$i]] = $tmp;
				}
			}

			// 解析剩余的URL参数
			$res = preg_replace('@(\w+)\/([^,\/]+)@e', '$var[\'\\1\']="\\2";', implode('/', $params));
			$_GET = array_merge($var, $_GET);
			return true;
		}elseif (isset($routers[$router_name . '*']) && !empty($routers[$router_name . '*'])) {
			// 正则路由定义
			$router = $routers[$router_name . '*'];
			$depr = C('sys_url_depr');
			foreach ($router as $key => $rule) {
				if (preg_match($rule[4], implode($depr, $params), $matches)) {
					$var[C('var_module')] = !empty($rule[0]) ? $rule[0] : array_shift($params);
					$var[C('var_controller')] = !empty($rule[1]) ? $rule[1] : array_shift($params);
					$var[C('var_action')] = !empty($rule[2]) ? $rule[2] : array_shift($params);

					// 处理路由规则的路由参数
					$vars = $rule[3];
					if ($vars) {
						$vars = explode(',', $vars);
						for ($i = 0; $i < count($vars); $i++)
							$var[$vars[$i]] = array_shift($params);
					}

					// 解析剩余的URL参数
					$res = preg_replace('@(\w+)\/([^,\/]+)@e', '$var[\'\\1\']="\\2";', implode('/', $params));
					$_GET = array_merge($var, $_GET);
					return true;
				}
			}
		}
		return false;
	}

	//获得服务器的PATH_INFO信息
	public static function getPathInfo() {
		if (!empty($_SERVER['PATH_INFO'])) {
			$pathInfo = $_SERVER['PATH_INFO'];
			if (0 === strpos($pathInfo, $_SERVER['SCRIPT_NAME']))
				$path = substr($pathInfo, strlen($_SERVER['SCRIPT_NAME']));
			else
				$path = $pathInfo;
		}elseif (!empty($_SERVER['ORIG_PATH_INFO'])) {
			$pathInfo = $_SERVER['ORIG_PATH_INFO'];
			if (0 === strpos($pathInfo, $_SERVER['SCRIPT_NAME']))
				$path = substr($pathInfo, strlen($_SERVER['SCRIPT_NAME']));
			else
				$path = $pathInfo;
		}elseif (!empty($_SERVER['REDIRECT_PATH_INFO'])) {
			$path = $_SERVER['REDIRECT_PATH_INFO'];
		} elseif (!empty($_SERVER["REDIRECT_Url"])) {
			$path = $_SERVER["REDIRECT_Url"];
			if (empty($_SERVER['QUERY_STRING']) || $_SERVER['QUERY_STRING'] == $_SERVER["REDIRECT_QUERY_STRING"]) {
				$parsedUrl = parse_url($_SERVER["REQUEST_URI"]);
				if (!empty($parsedUrl['query'])) {
					$_SERVER['QUERY_STRING'] = $parsedUrl['query'];
					parse_str($parsedUrl['query'], $GET);
					$_GET = array_merge($_GET, $GET);
					reset($_GET);
				} else {
					unset($_SERVER['QUERY_STRING']);
				}
				reset($_SERVER);
			}
		}
		if (C('sys_url_suffix') && !empty($path)) {
			$suffix = substr(C('sys_url_suffix'), 1);
			$path = preg_replace('/\.' . $suffix . '$/', '', $path);
		}
		$_SERVER['PATH_INFO'] = empty($path) ? '/' : $path;
	}

	//获得模块名称
	static public function getModule($var='') {
		$var = $var ? $var : C('var_module');
		$name = !empty($_GET[$var]) ? $_GET[$var] : C('sys_default_module');
		unset($_GET[$var]);
		return strtolower($name);
	}

	//获得控制器名称
	static public function getController($var='') {
		$var = $var ? $var : C('var_controller');
		$name = !empty($_GET[$var]) ? $_GET[$var] : C('sys_default_controller');
		unset($_GET[$var]);
		return strtolower($name);
	}

	//获得操作名称
	static public function getAction($var='') {
		$var = $var ? $var : C('var_action');
		$name = !empty($_GET[$var]) ? $_GET[$var] : C('sys_default_action');
		unset($_GET[$var]);
		return strtolower($name);
	}

	//url构造函数
	static public function U($url, $params=array(), $url_mode='') {
		if (!is_numeric($url_mode))  $url_mode = C('sys_url_mode');
		$u = self::formatUrlStr($url); //格式化url字符串
		$def = array();
		$get = '';
		$def['m'] = C('sys_default_module');
		$def['c'] = C('sys_default_controller');
		$def['a'] = C('sys_default_action');
		$s = $url_mode==0 ? '&' : C('sys_url_depr');
		
		//开始处理url组合
		if ($url_mode > 0) {
			if($u['get']){
				foreach ($u['get'] as $k => $v) {
					$get .= $k.$s.$v.$s;
				}
			}

			if($u['m']==$def['m'] && $u['c']==$def['c'] && $u['a']==$def['a'] && empty($u['get'])){
				$url = '';
			}else{
				$url = '/' . $u['m'] . $s . $u['c'] . $s . $u['a'] . $s . $get;
				if(C('sys_url_suffix')){
					$url = rtrim($url, $s);
					$url .= C('sys_url_suffix');
				}
			}

			//url路径模式处理
			if ($url_mode == URL_REWRITE) {
				$phpfile = dirname(_PHP_FILE_);
				if ($phpfile == '\\' || $phpfile == '/')  $phpfile = '';
				if(empty($phpfile)&&empty($url))  $url = '/';
			}else {
				$phpfile = _PHP_FILE_;
			}
			$url = $phpfile . $url;
		} else {
			if($u['get'])  $get = http_build_query($u['get']);
			if($u['m']==$def['m'] && $u['c']==$def['c'] && $u['a']==$def['a'] && empty($u['get'])){
				$url = _PHP_FILE_;
			}else{
				$url = '?'.C('var_module').'='.$u['m'].$s.C('var_controller').'='.$u['c'].$s.C('var_action').'='.$u['a'].$s.$get;
				$url = _PHP_FILE_.rtrim($url, $s);
			}
		}
		if (C('sys_domain'))  $url = get_url() . $url;
		return $url;
	}

	//url字符串分析 route@admin-user/info?v1=1&v2=2
	static public function formatUrlStr($url) {
		if (0 === strpos($url, '/'))
			$url = substr($url, 1);
		if (!strpos($url, '://')) // 没有指定项目名 使用当前项目名
			$url = 'fee://' . $url;

		// 分析URL地址
		$array = parse_url($url);
		$route = C('_route_');
		$app = ('fee' == $array['scheme']) ? '' : $array['scheme'];
		$route = isset($array['user']) && isset($route[$array['user']]) ? $array['user'] : '';
		$module = MODULE_NAME;
		if (isset($array['path'])) {
			//指定了模块和操作
			$action = substr($array['path'], 1);
			if (strpos($array['host'], '-')) {
				list($module, $controller) = explode('-', $array['host']);
			} else {
				$controller = $array['host'];
			}
		} else {
			//只指定操作
			$controller = CONTROLLER_NAME;
			$action = $array['host'];
		}
		//处理GET参数
		$query = array();
		if(isset($array['query'])){
			parse_str($array['query'], $query);
		}
		
		$var = array();
		//$var['app'] = $app;
		$var['r'] = $route;
		$var['m'] = $module;
		$var['c'] = $controller;
		$var['a'] = $action;
		$var['get'] = $query;
		return $var;
	}

}

?>